/*
* Copyright © 2021 Sturnus Inc.

* Permission is hereby granted, free of charge, to any person obtaining a copy
of this
* software and associated documentation files (the “Software”), to deal in the
Software
* without restriction, including without limitation the rights to use, copy,
modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software, and to
permit persons
* to whom the Software is furnished to do so, subject to the following
conditions:
*
* The above copyright notice and this permission notice shall be included in all
copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE
* SOFTWARE.
*/

#include <esp_log.h>
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
#include <lvgl.h>
#else
#include <lvgl/lvgl.h>
#endif

#include "cst816.h"

#include "lvgl_i2c/i2c_manager.h"

#define TAG "CST816T"

static cst816t_status_t cst816t_status;

esp_err_t cst816t_i2c_read(uint8_t slave_addr, uint16_t register_addr,
                           uint8_t *data_buf, uint8_t len) {
  return lvgl_i2c_read(CONFIG_LV_I2C_TOUCH_PORT, slave_addr,
                       register_addr | I2C_REG_16, data_buf, len);
}

uint8_t cst816t_chipId(void) { return 0; }
static esp_err_t cst816t_get_touch_points_num(uint8_t *touch_points_num) {
  uint8_t res = 0;
  res = cst816t_i2c_read(CST816T_ADDR, 0x02, touch_points_num, 1);
  return res;
}

esp_err_t cst816t_read_pos(uint8_t *touch_points_num, uint16_t *x,
                           uint16_t *y) {
  uint8_t data[4];

  cst816t_get_touch_points_num(touch_points_num);
  if (0 == *touch_points_num) {
    *x = 0;
    *y = 0;
    return 1;
  } else {
    cst816t_i2c_read(CST816T_ADDR, 0x03, data, 4);

    *x = ((data[0] & 0x0f) << 8) | data[1];
    *y = ((data[2] & 0x0f) << 8) | data[3];
  }

  return ESP_OK;
}

#define TP_RST_PIN 13

void cst816t_init(uint16_t dev_addr) {
  if (!cst816t_status.inited) {
    cst816t_status.i2c_dev_addr = dev_addr;
    uint8_t data_buf[10];
    esp_err_t ret;

    esp_rom_gpio_pad_select_gpio(TP_RST_PIN);
    gpio_set_direction(TP_RST_PIN, GPIO_MODE_OUTPUT);

    gpio_set_level(TP_RST_PIN, 0);
    vTaskDelay(100 / portTICK_PERIOD_MS);
    gpio_set_level(TP_RST_PIN, 1);
    vTaskDelay(100 / portTICK_PERIOD_MS);

    ESP_LOGI(TAG, "Checking for CST816T Touch Controller ");

    if ((ret = cst816t_i2c_read(dev_addr, 0x15, &data_buf, 1) != ESP_OK)) {
      vTaskDelay(pdMS_TO_TICKS(10));
      ESP_LOGE(TAG, "Error reading from device: %s",
               esp_err_to_name(ret)); // Only show error the first time
                                      // return;
    }
    if ((ret = cst816t_i2c_read(dev_addr, 0xa7, &data_buf, 1) != ESP_OK)) {
      ESP_LOGE(TAG, "Error reading from device: %s",
               esp_err_to_name(ret)); // Only show error the first time

      // return;
    }
    ESP_LOGI(TAG, "device ID: %02x", data_buf[0]);
    cst816t_status.inited = true;
  }
}

bool cst816t_read(lv_indev_t *drv, lv_indev_data_t *data) {

  uint8_t touch_points_num = 0;
  static uint16_t last_x = 0;
  static uint16_t last_y = 0;

  cst816t_read_pos(&touch_points_num, &last_x, &last_y);

  if (touch_points_num > 0) {
    int16_t swap_buf = last_x;
    last_x = 280 - last_y;
    last_y = swap_buf;

    data->point.x = last_x;
    data->point.y = last_y;
    data->state = LV_INDEV_STATE_PR;
    // ESP_LOGI(TAG, "X=%ld Y=%ld", data->point.x, data->point.y);
    //  ESP_LOGV(TAG, "X=%u Y=%u", data->point.x, data->point.y);
    return true;
  } else {
    data->point.x = last_x;
    data->point.y = last_y;
    data->state = LV_INDEV_STATE_REL;
    return false;
  }
}